import asyncio

from redis import asyncio as aioredis
from redis.exceptions import AuthenticationError, TimeoutError, RedisError
from common.config.env import RedisConfig
from common.utils.log_util import logger
from fastapi import Request

class RedisUtil:
    """
    Redis相关方法
    """

    @classmethod
    async def create_redis_pool(cls) -> aioredis.Redis:
        """
        应用启动时初始化redis连接

        :return: Redis连接对象或None
        """
        logger.info('开始连接redis...')
        try:
            redis = await aioredis.from_url(
                url=f'redis://{RedisConfig.redis_host}',
                port=RedisConfig.redis_port,
                username=RedisConfig.redis_username,
                password=RedisConfig.redis_password,
                db=RedisConfig.redis_database,
                encoding='utf-8',
                decode_responses=True,
            )
            connection = await redis.ping()
            if connection:
                logger.info('redis连接成功')
                return redis
            else:
                logger.error('redis连接失败')
                return None
        except AuthenticationError as e:
            logger.error(f'redis用户名或密码错误，详细错误信息：{e}')
        except TimeoutError as e:
            logger.error(f'redis连接超时，详细错误信息：{e}')
        except RedisError as e:
            logger.error(f'redis连接错误，详细错误信息：{e}')
        except Exception as e:
            logger.error(f'redis初始化异常：{e}')
        return None

    @classmethod
    async def keepalive(cls, redis: aioredis.Redis, interval: int = 30):
        """
        定期发送PING命令以保持连接活跃

        :param redis: Redis连接对象
        :param interval: 发送PING命令的时间间隔（秒）
        """
        while True:
            try:
                await redis.ping()
                logger.debug('Redis连接保持活跃')
            except RedisError as e:
                logger.error(f'Redis心跳检测失败，详细错误信息：{e}')
            await asyncio.sleep(interval)

    @classmethod
    async def close_redis_pool(cls, app):
        """
        应用关闭时关闭redis连接

        :param app: fastapi对象
        :return:
        """
        await app.state.redis.close()
        logger.info('关闭redis连接成功')

    # redis操作方法
    @staticmethod
    async def get_redis_value(request: Request, key: str):
        """
        获取redis值
        :param key: redis键
        :return: redis值
        """
        key=str(351)+":"+key
        return await request.app.state.redis.get(key)
    @staticmethod
    async def set_redis_value(request: Request, key: str, value: str, expire: str = None):
        """
        设置redis值
        :param key: redis键
        :param value: redis值
        :param expire: 过期时间，单位秒
        :return:
        """
        key=str(351)+":"+key
        return await request.app.state.redis.set(key, value, ex=expire)
    #删除
    @staticmethod
    async def delete_redis_value(request: Request, key: str):
        """
        删除redis值
        :param key: redis键
        :return:
        """
        key=str(351)+":"+key
        return await request.app.state.redis.delete(key)

